﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Invoicing.Messages;
using PServiceBus.Services.Gateway.Runtime;
using PServiceBus.Core.Runtime.Transports;
using PServiceBus.Transports;
using System.Diagnostics;

namespace Invoicing {
    class Program {
        static int _counter = 0;
        static int GetPort() {
            return Process.GetCurrentProcess().Id + (++_counter);
        }
        static void Main(string[] args) {
            //Register Topics
                Topic.RegisterIfNotExist<InvoiceRequest>();
 
                Topic.RegisterIfNotExist<AccountInformation>();

                Topic.RegisterIfNotExist<InvoiceInformation>();

                Topic.RegisterIfNotExist<PDFInformation>();

                Topic.RegisterIfNotExist<PrintInformation>();

            Create<InvoiceRequest>("InvoiceService",
                msg => {
                    Console.WriteLine("Received Invoice Request with ID = {0} for Invoice Service",
                        msg.ID);
                    Topic.PublishMessage<InvoiceInformation>(
                        new InvoiceInformation() { Amount = msg.Amount,
                        Customer = msg.Customer, ID = msg.ID});
                    Console.WriteLine("Published Invoice Information From Invoice Service");
                });

            Create<InvoiceInformation>("PDFService",
                msg => {
                    Console.WriteLine("Received Invoice Information with ID = {0} for PDF Service",
                        msg.ID);
                    Topic.PublishMessage<PDFInformation>(
                        new PDFInformation() { 
                            Location = String.Format("filename{0}",
                                new Random().Next(10000))
                        });
                    Console.WriteLine("Published PDF Information From PDF Service");
                });

            Create<InvoiceInformation>("AccountService",
                msg => {
                    Console.WriteLine("Received Invoice Information with ID = {0} for Account Service",
                        msg.ID);
                    Topic.PublishMessage<AccountInformation>(
                        new AccountInformation() { 
                            Detail = "This is the account information"
                        });
                    Console.WriteLine("Published Account Information From Account Service");
                });

            Create<PDFInformation>("PrintService",
                msg => {
                    Console.WriteLine("Received PDF Information with Location = {0} for Print Service ",
                        msg.Location);
                    Topic.PublishMessage<PrintInformation>(
                        new PrintInformation() { 
                            Location = msg.Location,
                            Success = true
                        });
                    Console.WriteLine("Published Printing information From Print Service");
                });

            Create<PrintInformation>("ManagementService",
                msg => {
                    Console.WriteLine("Received Print Information with Location = {0} for Management Service", 
                        msg.Location);
                    Console.WriteLine("-----------------------------------------------------------------------");
                });

            Create<AccountInformation>("ManagementService",
                msg =>
                {
                    Console.WriteLine("Received Account Information with Detail = {0} for Management Service",
                        msg.Detail);
                    Console.WriteLine("-----------------------------------------------------------------------");
                });
            Console.WriteLine("Waiting for Invoice Request(s)...... Press enter to exit");
            Console.ReadLine();
            TransportHandlers.ShutDown();
            var subscribers = new[] { "InvoiceService", "PDFService", "ManagementService", "PrintService", "AccountService"};
            foreach (var subscriber in subscribers) Subscriber.Select(subscriber).Delete();
        }
        static void Create<TSubscribeTo>(string subscriberName, Action<TSubscribeTo> msgAction) where TSubscribeTo: class {
            var type = typeof(TSubscribeTo);
            var topicName = type.Name;
            var subscriber = Subscriber.SelectOrAdd(subscriberName);
            subscriber = Subscriber.Select(subscriberName);
            subscriber
                .SubscribeTo(Topic.Select<TSubscribeTo>())
                 .AddTransport(topicName, Transport.New<TcpTransport>(
                    transport => { 
                        transport.Format = TransportFormat.Xml; 
                        transport.IPAddress = "127.0.0.1";
                        transport.Port = GetPort();
                    }), topicName)
                ;
            subscriber.Save();

            subscriber.OnMessageReceived<TSubscribeTo>(topicName, msgAction,
            interval: TimeSpan.FromMilliseconds(1),
            errorAction: h =>
            {
                h.Continue = true;
                Console.WriteLine(h.Error.ToString());
            });
        }
    }
}
